
package id.isran.kamusindonesiamuna.basisdata;

import id.isran.kamusindonesiamuna.utils.Utils;

import java.io.BufferedInputStream;
import java.io.BufferedReader;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;

import android.content.Context;
import android.util.Log;

public class Data {
    // variable untuk definisi kamus
    public static final int INDO_MUNA = 0;
    public static final int MUNA_INDO = 1;

    // variable untuk definisi kolom di kamus
    public static final int INDEX_KONVERSI = 0;
    public static final int INDEX_KATA = 1;
    public static final int INDEX_TERJEMAHAN = 2;
    public static final int INDEX_JENIS = 3;

    // variable untuk definisi lokasi kamus di asset
    private static final String KAMUS = "kamus/";
    private static final String fileIndoMuna = KAMUS + "indomuna.txt";
    private static final String fileMunaIndo = KAMUS + "munaindo.txt";

    // fix jumlah kolom untuk setiap database
    private static int KOLOM_COUNT = 4;

    // variable untuk save jumlah baris dari kamus
    public static int BARIS_COUNT_INA_MUNA = 0;
    public static int BARIS_COUNT_MUNA_INA = 0;

    // buffered reader untuk membaca file
    public static BufferedReader reader;

    // array 2 dimensi untuk menyimpan data kamus
    public static String[][] dataInaMuna;
    public static String[][] dataMunaIna;

    // separator/ pemisah file dari kamus
    private static final String SEPARATOR = "_";

    /**
     * init data, atau baca data dari folder asset, kemudian disimpan dalam
     * array 2 dimensi
     * 
     * @param context
     * @param fileType
     */
    public static void initData(Context context, int fileType) {
        try {
            InputStreamReader is;
            if (fileType == INDO_MUNA) {
                is = new InputStreamReader(context.getAssets().open(fileIndoMuna));
                BARIS_COUNT_INA_MUNA = count(context.getAssets().open(fileIndoMuna));
            } else {
                is = new InputStreamReader(context.getAssets().open(fileMunaIndo));
                BARIS_COUNT_MUNA_INA = count(context.getAssets().open(fileMunaIndo));
            }

            reader = new BufferedReader(is, 16);
            isiData(reader, fileType);
            is.close();
            reader.close();
        } catch (Exception e) {
            Utils.TRACE("Data", e.getMessage());
        }
    }

    /**
     * method untuk isi data ke array dua dimensi
     * 
     * @param reader
     * @param fileType
     */
    private static void isiData(BufferedReader reader, int fileType) {
        String line = null;
        if (fileType == INDO_MUNA) {
            Utils.TRACE("Data", "isiData: INDO MUNA");
            dataInaMuna = new String[BARIS_COUNT_INA_MUNA + 1][KOLOM_COUNT];
            String[] pecah = null;
            int baris = 0;
            try {
                while ((line = reader.readLine()) != null) {
                    pecah = line.split(SEPARATOR);
                    for (int kolom = 0; kolom < KOLOM_COUNT; kolom++) {
                        dataInaMuna[baris][kolom] = pecah[kolom];
                    }
                    baris++;
                }
            } catch (IOException e) {
                Utils.TRACE("Data", "isiData: " + e.getMessage());
            }
        } else if (fileType == MUNA_INDO) {
            Utils.TRACE("Data", "isiData: muna indo");
            dataMunaIna = new String[BARIS_COUNT_MUNA_INA + 1][KOLOM_COUNT];
            String[] pecah = null;
            int baris = 0;
            try {
                while ((line = reader.readLine()) != null) {
                    pecah = line.split(SEPARATOR);
                    for (int kolom = 0; kolom < KOLOM_COUNT; kolom++) {
                        dataMunaIna[baris][kolom] = pecah[kolom];
                    }
                    baris++;
                }
            } catch (IOException e) {
                Utils.TRACE("Data", "isiData: " + e.getMessage());
            }
        }
    }

    /**
     * method untuk hitung jumlah baris
     * 
     * @param filename
     * @return
     */
    private static int count(InputStream filename) {
        try {
            InputStream is = new BufferedInputStream(filename);
            byte[] c = new byte[1024];
            int count = 0;
            int readChars = 0;
            boolean empty = true;
            while ((readChars = is.read(c)) != -1) {
                empty = false;
                for (int i = 0; i < readChars; ++i) {
                    if (c[i] == '\n') {
                        ++count;
                    }
                }
            }
            is.close();
            return (count == 0 && !empty) ? 1 : count;
        } catch (FileNotFoundException e) {
            Log.d("error", "" + e.getMessage());
        } catch (IOException e) {

            Log.d("error", "" + e.getMessage());
        }
        return 0;

    }

    /**
     * Cari arti dari sebuah kata
     * <p>
     * (index!=-1)?true:false
     * </p>
     * <p>
     * dicek apakah index tidak sama dengan (!=-1) jika benar maka kembalikan
     * data dari index tersebut jika salah kembalikan string kosong ""
     * </p>
     * 
     * @param name kata yang ingin dicari artinya
     * @return hasil terjemahan
     */
    public static String cariKata(String name, int kamus) {
        int index = -1;

        if (kamus == INDO_MUNA) {
            for (int i = 0; i < BARIS_COUNT_INA_MUNA + 1; i++) {
                if (name.equals(dataInaMuna[i][INDEX_KATA]))
                    index = i;
            }
            return (index != -1) ? dataInaMuna[index][INDEX_TERJEMAHAN] + " ("
                    + dataInaMuna[index][INDEX_JENIS]
                    + ")" : "";
        } else {
            for (int i = 0; i < BARIS_COUNT_MUNA_INA + 1; i++) {
                if (name.equals(dataMunaIna[i][INDEX_KATA]))
                    index = i;
            }
            return (index != -1) ? dataMunaIna[index][INDEX_TERJEMAHAN] + " ("
                    + dataMunaIna[index][INDEX_JENIS]
                    + ")" : "";
        }
    }

    /**
     * method untuk mendapatkan nilai konversi dari suatu kata
     * 
     * @param name kata yang ingin dicari nilai indexnya
     * @param kamus kamus muna atau indonesia
     * @return
     */
    public static int getNilaiKonversi(String name, int kamus) {
        int index = -1;
        Utils.TRACE("Data", "cari konversi : " + name);
        if (kamus == INDO_MUNA) {

            for (int i = 0; i < BARIS_COUNT_INA_MUNA + 1; i++) {
                if (name.equals(dataInaMuna[i][INDEX_KATA]))
                    index = i;
            }
            return (index != -1) ? Integer.parseInt(dataInaMuna[index][0]) : -1;

        } else {
            for (int i = 0; i < BARIS_COUNT_MUNA_INA + 1; i++) {
                if (name.equals(dataMunaIna[i][INDEX_KATA]))
                    index = i;
            }
            return (index != -1) ? Integer.parseInt(dataMunaIna[index][0]) : -1;
        }
    }

    /**
     * Interpolation algorithm
     * 
     * @param key
     * @return
     */
    public static int interpolationSearch(int key, int kamus) {
        Utils.TRACE("Data", "cari key " + key);
        int min = 0;
        int max = 0;
        if (kamus == INDO_MUNA) {
            max = Integer.parseInt(dataInaMuna[BARIS_COUNT_INA_MUNA][0]) - 1;
        } else {
            max = Integer.parseInt(dataMunaIna[BARIS_COUNT_MUNA_INA][0]) - 1;
        }
        int mid = 0;

        if (key != -1) {
            if (kamus == INDO_MUNA) {
                do {

                    // cari nilai tengah
                    mid = ((key - Integer.parseInt(dataInaMuna[min][0]))
                            / (Integer.parseInt(dataInaMuna[max][0]) - Integer
                                    .parseInt(dataInaMuna[min][0]))
                            * (max - min) + min);

                    // jika nilai konversi ditengah sama dengan nilai konversi
                    // yang
                    // dicari, kembalikan index tengah
                    if (dataInaMuna[mid][0].equals(String.valueOf(key))) {
                        return mid;
                    } else if (key < Integer.parseInt(dataInaMuna[mid][0])) {

                        // jikai nilai konversi yang dicari kurang dari nilai
                        // konversi
                        // di index mid, maka nilai max= mid-1

                        Utils.TRACE("data", "naik keatas");
                        max = mid - 1;
                    } else {
                        // jikai nilai konversi yang dicari lebih dari nilai
                        // konversi
                        // di index mid, maka nilai max= mid+1
                        Utils.TRACE("data", "turun kebawah");
                        min = mid + 1;
                    }
                } while (key >= Integer.parseInt(dataInaMuna[min][0]) && key <=
                        Integer.parseInt(dataInaMuna[max][0]));
            } else {

                do {

                    // cari nilai tengah
                    mid = ((key - Integer.parseInt(dataMunaIna[min][0]))
                            / (Integer.parseInt(dataMunaIna[max][0]) - Integer
                                    .parseInt(dataMunaIna[min][0]))
                            * (max - min) + min);

                    // jika nilai konversi ditengah sama dengan nilai konversi
                    // yang
                    // dicari, kembalikan index tengah
                    if (dataMunaIna[mid][0].equals(String.valueOf(key))) {
                        return mid;
                    } else if (key < Integer.parseInt(dataMunaIna[mid][0])) {

                        // jikai nilai konversi yang dicari kurang dari nilai
                        // konversi
                        // di index mid, maka nilai max= mid-1

                        Utils.TRACE("data", "naik keatas");
                        max = mid - 1;
                    } else {
                        // jikai nilai konversi yang dicari lebih dari nilai
                        // konversi
                        // di index mid, maka nilai max= mid+1
                        Utils.TRACE("data", "turun kebawah");
                        min = mid + 1;
                    }
                } while (key >= Integer.parseInt(dataMunaIna[min][0]) && key <=
                        Integer.parseInt(dataMunaIna[max][0]));

            }

        }
        return -1;
    }
}
